14 public function importPlan()
16 $plan = json_decode(file_get_contents(ROOT
. '/include/data/plan_comptable.json'), true);
18 $db = DB
::getInstance();
22 foreach ($plan as $id=>$compte)
26 if ($db->simpleQuerySingle('SELECT 1 FROM compta_comptes WHERE id = ?;', false, $id))
28 $db->simpleUpdate('compta_comptes', [
29 'parent' => $compte['parent'],
30 'libelle' => $compte['nom'],
31 'position' => $compte['position'],
32 'plan_comptable' => 1,
33 ], 'id = \''.$db->escapeString($id).'\'');
37 $db->simpleInsert('compta_comptes', [
39 'parent' => $compte['parent'],
40 'libelle' => $compte['nom'],
41 'position' => $compte['position'],
42 'plan_comptable' => 1,
47 $db->exec('DELETE FROM compta_comptes WHERE id NOT IN(\''.implode('\', \'', $ids).'\') AND plan_comptable = 1;');
54 public function add($data)
56 $this->_checkFields($data, true);
58 $db = DB
::getInstance();
60 if (empty($data['id']))
62 $new_id = $data['parent'];
63 $nb_sous_comptes = $db->simpleQuerySingle('SELECT COUNT(*) FROM compta_comptes WHERE parent = ?;', false, $new_id);
65 // Pas plus de 26 sous-comptes par compte, parce que l'alphabet s'arrête à 26 lettres
66 if ($nb_sous_comptes >= 26)
68 throw new UserException('Nombre de sous-comptes maximal atteint pour ce compte parent-ci.');
71 $new_id .= chr(65+
(int)$nb_sous_comptes);
75 $new_id = $data['id'];
78 if (isset($data['position']))
80 $position = (int) $data['position'];
84 $position = $db->simpleQuerySingle('SELECT position FROM compta_comptes WHERE id = ?;', false, $data['parent']);
87 $db->simpleInsert('compta_comptes', [
89 'libelle' => trim($data['libelle']),
90 'parent' => $data['parent'],
91 'plan_comptable' => 0,
92 'position' => (int)$position,
98 public function edit($id, $data)
100 $db = DB
::getInstance();
102 // Vérification que l'on peut éditer ce compte
103 if ($db->simpleQuerySingle('SELECT plan_comptable FROM compta_comptes WHERE id = ?;', false, $id))
105 throw new UserException('Ce compte fait partie du plan comptable et n\'est pas modifiable.');
108 if (isset($data['position']) && empty($data['position']))
110 throw new UserException('Aucune position du compte n\'a été indiquée.');
113 $this->_checkFields($data);
116 'libelle' => trim($data['libelle']),
119 if (isset($data['position']))
121 $update['position'] = (int) trim($data['position']);
124 $db->simpleUpdate('compta_comptes', $update, 'id = \''.$db->escapeString(trim($id)).'\'');
129 public function delete($id)
131 $db = DB
::getInstance();
133 // Ne pas supprimer un compte qui est utilisé !
134 if ($db->simpleQuerySingle('SELECT 1 FROM compta_journal WHERE compte_debit = ? OR compte_debit = ? LIMIT 1;', false, $id, $id))
136 throw new UserException('Ce compte ne peut être supprimé car des opérations comptables y sont liées.');
139 if ($db->simpleQuerySingle('SELECT 1 FROM compta_comptes_bancaires WHERE id = ? LIMIT 1;', false, $id))
141 throw new UserException('Ce compte ne peut être supprimé car il est lié à un compte bancaire.');
144 if ($db->simpleQuerySingle('SELECT 1 FROM compta_categories WHERE compte = ? LIMIT 1;', false, $id))
146 throw new UserException('Ce compte ne peut être supprimé car des catégories y sont liées.');
149 $db->simpleExec('DELETE FROM compta_comptes WHERE id = ?;', trim($id));
155 * Peut-on supprimer ce compte ? (OUI s'il n'a pas d'écriture liée)
156 * @param string $id Numéro du compte
157 * @return boolean TRUE si le compte n'a pas d'écriture liée
159 public function canDelete($id)
161 $db = DB
::getInstance();
163 if ($db->simpleQuerySingle('SELECT 1 FROM compta_journal
164 WHERE compte_debit = ? OR compte_debit = ? LIMIT 1;', false, $id, $id))
169 if ($db->simpleQuerySingle('SELECT 1 FROM compta_categories WHERE compte = ? LIMIT 1;', false, $id))
178 * Peut-on désactiver ce compte ? (OUI s'il n'a pas d'écriture liée dans l'exercice courant)
179 * @param string $id Numéro du compte
180 * @return boolean TRUE si le compte n'a pas d'écriture liée dans l'exercice courant
182 public function canDisable($id)
184 $db = DB
::getInstance();
186 if ($db->simpleQuerySingle('SELECT 1 FROM compta_journal
187 WHERE id_exercice = (SELECT id FROM compta_exercices WHERE cloture = 0 LIMIT 1)
188 AND (compte_debit = ? OR compte_debit = ?) LIMIT 1;', false, $id, $id))
193 if ($db->simpleQuerySingle('SELECT 1 FROM compta_categories WHERE compte = ? LIMIT 1;', false, $id))
202 * Désactiver un compte
203 * Le compte ne sera plus utilisable pour les écritures ou les catégories mais restera en base de données
204 * @param string $id Numéro du compte
205 * @return boolean TRUE si la désactivation a fonctionné, une exception utilisateur si
206 * la désactivation n'est pas possible.
208 public function disable($id)
210 $db = DB
::getInstance();
212 // Ne pas désactiver un compte utilisé dans l'exercice courant
213 if ($db->simpleQuerySingle('SELECT 1 FROM compta_journal
214 WHERE id_exercice = (SELECT id FROM compta_exercices WHERE cloture = 0 LIMIT 1)
215 AND (compte_debit = ? OR compte_debit = ?) LIMIT 1;', false, $id, $id))
217 throw new UserException('Ce compte ne peut être désactivé car des écritures y sont liées sur l\'exercice courant. '
218 . 'Il faut supprimer ou ré-attribuer ces écritures avant de pouvoir supprimer le compte.');
221 // Ne pas désactiver un compte utilisé pour une catégorie
222 if ($db->simpleQuerySingle('SELECT 1 FROM compta_categories WHERE compte = ? LIMIT 1;', false, $id))
224 throw new UserException('Ce compte ne peut être désactivé car des catégories y sont liées.');
227 return $db->simpleUpdate('compta_comptes', ['desactive' => 1], 'id = \''.$db->escapeString(trim($id)).'\'');
230 public function get($id)
232 $db = DB
::getInstance();
233 return $db->simpleQuerySingle('SELECT * FROM compta_comptes WHERE id = ?;', true, trim($id));
236 public function getList($parent = 0)
238 $db = DB
::getInstance();
239 return $db->simpleStatementFetchAssocKey('SELECT id, * FROM compta_comptes WHERE parent = ? ORDER BY id;', SQLITE3_ASSOC
, $parent);
242 public function getListAll($parent = 0)
244 $db = DB
::getInstance();
245 return $db->queryFetchAssoc('SELECT id, libelle FROM compta_comptes ORDER BY id;');
248 public function listTree($parent = 0, $include_children = true)
250 $db = DB
::getInstance();
252 if ($include_children)
254 $parent = $parent ?
'WHERE parent LIKE \''.$db->escapeString($parent).'%\' ' : '';
258 $parent = $parent ?
'WHERE parent = \''.$db->escapeString($parent).'\' ' : 'WHERE parent = 0';
261 return $db->simpleStatementFetch('SELECT * FROM compta_comptes '.$parent.' ORDER BY id;');
264 protected function _checkFields(&$data, $force_parent_check = false)
266 $db = DB
::getInstance();
268 if (empty($data['libelle']) ||
!trim($data['libelle']))
270 throw new UserException('Le libellé ne peut rester vide.');
273 $data['libelle'] = trim($data['libelle']);
275 if (isset($data['id']))
277 $force_parent_check = true;
278 $data['id'] = trim($data['id']);
280 if ($db->simpleQuerySingle('SELECT 1 FROM compta_comptes WHERE id = ?;', false, $data['id']))
282 throw new UserException('Le compte numéro '.$data['id'].' existe déjà.');
286 if (isset($data['parent']) ||
$force_parent_check)
288 if (empty($data['parent']) && !trim($data['parent']))
290 throw new UserException('Le compte ne peut pas ne pas avoir de compte parent.');
293 if (!($id = $db->simpleQuerySingle('SELECT id FROM compta_comptes WHERE id = ?;', false, $data['parent'])))
295 throw new UserException('Le compte parent indiqué n\'existe pas.');
298 $data['parent'] = trim($id);
301 if (isset($data['id']))
303 if (strncmp($data['id'], $data['parent'], strlen($data['parent'])) !== 0)
305 throw new UserException('Le compte '.$data['id'].' n\'est pas un sous-compte de '.$data['parent'].'.');
312 public function getPositions()
315 self
::ACTIF
=> 'Actif',
316 self
::PASSIF
=> 'Passif',
317 self
::ACTIF | self
::PASSIF
=> 'Actif ou passif (déterminé automatiquement au bilan selon le solde du compte)',
318 self
::CHARGE
=> 'Charge',
319 self
::PRODUIT
=> 'Produit',
320 self
::CHARGE | self
::PRODUIT
=> 'Charge et produit',